﻿using Microsoft.Graphics.Canvas;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using TimelineService.Beans;
using TimelineService.Inis;
using TimelineService.Utils;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Background;
using Windows.ApplicationModel.Core;
using Windows.Data.Xml.Dom;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Streams;
using Windows.System.UserProfile;
using Windows.UI;
using Windows.UI.Notifications;
using Windows.UI.StartScreen;

namespace TimelineService {
    public sealed class PushService : IBackgroundTask {
        BackgroundTaskDeferral _deferral;
        private ApplicationDataContainer localSettings;
        private AppIni ini;
        private float periodDesktop = 24;
        private float periodLock = 24;
        private float periodTile = 2;
        private string tagDesktop; // 免重复推送桌面背景标记
        private string tagLock; // 免重复推送锁屏背景标记
        private string tagTile; // 免重复推送磁贴背景标记
        private string tagApiLog; // 免重复提交日志标记
        private bool pushNow = false; // 立即运行一次

        private enum Action {
            Desktop, Lock, Tile
        }

        public async void Run(IBackgroundTaskInstance taskInstance) {
            // IBackgroundTaskInstance.TriggerDetails
            // If the background task is triggered by a system event or time event, this property is not used.
            _deferral = taskInstance.GetDeferral();
            // 初始化
            Init(taskInstance);
            LogUtil.I("Run() trigger: " + taskInstance.TriggerDetails);
            LogUtil.I("Run() desktop: " + ini.DesktopProvider + ", " + periodDesktop);
            LogUtil.I("Run() lock: " + ini.LockProvider + ", " + periodLock);
            // 检查网络连接
            if (!NetworkInterface.GetIsNetworkAvailable()) {
                LogUtil.W("Run() network not available");
                _deferral.Complete();
                return;
            }
            bool pushDesktop = CheckDesktopNecessary();
            bool pushLock = CheckLockNecessary();
            bool pushTile = await CheckTileNecessaryAsync();
            bool pushApiLog = CheckApiLogNecessary();
            LogUtil.I(string.Format("Run() CheckNecessary: desktop {0} {1}, lock {2} {3}, tile {4} {5}, log {6} {7}",
                tagDesktop, pushDesktop, tagLock, pushLock, tagTile, pushTile, tagApiLog, pushApiLog));
            if (!pushDesktop && !pushLock && !pushTile) { // 本次无需推送
                _deferral.Complete();
                return;
            }
            // 上传统计
            if (pushApiLog) { // 一天同一图源上传一次日志即可
                localSettings.Values[tagApiLog] = (int)(localSettings.Values[tagApiLog] ?? 0) + 1;
                IReadOnlyDictionary<string, int> dosage = await FileUtil.ReadDosage();
                double scaleFactor = (double)(localSettings.Values["Scale"] ?? 0);
                double diagonalInch = (double)(localSettings.Values["Diagonal"] ?? 0);
                long resolution = (long)(localSettings.Values["Resolution"] ?? 0);
                long resW = (resolution & 0xffff0000) >> 16;
                long resH = resolution & 0x0000ffff;
                _ = await Api.Stats(ini, dosage.GetValueOrDefault("all", 0), 0,
                    string.Format("{0}x{1},{2},{3}", resW, resH, scaleFactor.ToString("0.00"), diagonalInch.ToString("0.0")));
            }
            // 在缓存可能被使用之前清理缓存
            await FileUtil.ClearCache(ini.Cache);
            // 开始推送
            try {
                if (pushDesktop) {
                    await PushDesktopAsync();
                }
                if (pushLock) {
                    await PushLockAsync();
                }
                if (pushTile) {
                    await PushTileAsync();
                }
            } catch (Exception e) {
                LogUtil.E("Run() " + e.Message);
            } finally {
                _deferral.Complete();
            }
        }

        private void Init(IBackgroundTaskInstance taskInstance) {
            pushNow = taskInstance.TriggerDetails is ApplicationTriggerDetails;
            ini = IniUtil.GetIni();
            periodDesktop = ini.GetDesktopPeriod(ini.DesktopProvider);
            periodLock = ini.GetLockPeriod(ini.LockProvider);
            int dayMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
            tagDesktop = string.Format("{0}{1}-{2}", DateTime.Now.ToString("yyyyMMdd"),
                Math.Ceiling(dayMinutes / (periodDesktop * 60)), ini.DesktopProvider);
            tagLock = string.Format("{0}{1}-{2}", DateTime.Now.ToString("yyyyMMdd"),
                Math.Ceiling(dayMinutes / (periodLock * 60)), ini.LockProvider);
            tagTile = string.Format("{0}{1}-{2}", DateTime.Now.ToString("yyyyMMdd"),
                Math.Ceiling(dayMinutes / (periodTile * 60)), ini.Provider);
            tagApiLog = string.Format("{0}-{1}", DateTime.Now.ToString("yyyyMMdd"), ini.Provider);

            if (localSettings == null) {
                localSettings = ApplicationData.Current.LocalSettings;
            }
        }

        private bool CheckDesktopNecessary() {
            if (string.IsNullOrEmpty(ini.DesktopProvider)) { // 未开启推送
                return false;
            }
            if (!UserProfilePersonalizationSettings.IsSupported()) { // 检查是否支持修改背景
                LogUtil.W("CheckDesktopNecessary() not supported");
                return false;
            }
            if (pushNow) { // 立即运行一次
                return ini.DesktopProvider.Equals(ini.Provider);
            }
            return !localSettings.Values.ContainsKey(tagDesktop);
        }

        private bool CheckLockNecessary() {
            if (string.IsNullOrEmpty(ini.LockProvider)) { // 未开启推送
                return false;
            }
            if (!UserProfilePersonalizationSettings.IsSupported()) { // 检查是否支持修改背景
                LogUtil.W("CheckLockNecessary() not supported");
                return false;
            }
            if (pushNow) { // 立即运行一次
                return ini.LockProvider.Equals(ini.Provider);
            }
            return !localSettings.Values.ContainsKey(tagLock);
        }

        private async Task<bool> CheckTileNecessaryAsync() {
            if (SysUtil.GetOsVerMajor() != 10) { // 检查 Win10
                return false;
            }
            AppListEntry entry = (await Package.Current.GetAppListEntriesAsync())[0];
            if (!await StartScreenManager.GetDefault().ContainsAppListEntryAsync(entry)) { // 检查当前是否已固定
                return false;
            }
            if (pushNow) { // 立即运行一次
                return true;
            }
            return !localSettings.Values.ContainsKey(tagTile);
        }

        private bool CheckApiLogNecessary() {
            if (string.IsNullOrEmpty(ini.LockProvider)) { // 未开启推送
                return false;
            }
            if (!UserProfilePersonalizationSettings.IsSupported()) { // 检查是否支持修改背景
                LogUtil.W("CheckLockNecessary() not supported");
                return false;
            }
            if (pushNow) { // 立即运行一次
                return true;
            }
            return !localSettings.Values.ContainsKey(tagApiLog);
        }

        private async Task<bool> PushDesktopAsync() {
            await FileUtil.WriteDosage(ini.DesktopProvider);
            bool res = false;
            if (A3gIni.GetId().Equals(ini.DesktopProvider)) {
                res = await Load3gAsync(Action.Desktop, pushNow);
            } else if (AbyssIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadAbyssAsync(Action.Desktop, pushNow);
            } else if (AdwestIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadAdwestAsync(Action.Desktop, pushNow);
            } else if (BackieeIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadBackieeAsync(Action.Desktop, pushNow);
            } else if (BingIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadBingAsync(Action.Desktop, pushNow);
            } else if (ColorhubIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadColorhubAsync(Action.Desktop, pushNow);
            } else if (EsoIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadEsoAsync(Action.Desktop, pushNow);
            } else if (FavoriteIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadFavoriteAsync(Action.Desktop, pushNow);
            } else if (GluttonIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadGluttonAsync(Action.Desktop, pushNow);
            } else if (Himawari8Ini.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadHimawari8Async(Action.Desktop);
            } else if (HuamaoIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadHuamaoAsync(Action.Desktop, pushNow);
            } else if (IuiIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadIuiAsync(Action.Desktop, pushNow);
            } else if (LocalIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadLocalAsync(Action.Desktop);
            } else if (LspIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadLspAsync(Action.Desktop, pushNow);
            } else if (NasaIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadNasaAsync(Action.Desktop, pushNow);
            } else if (NetbianIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadNetbianAsync(Action.Desktop, pushNow);
            } else if (ObzhiIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadObzhiAsync(Action.Desktop, pushNow);
            } else if (OneIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadOneAsync(Action.Desktop, pushNow);
            } else if (PexelsIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadPexelsAsync(Action.Desktop, pushNow);
            } else if (QingbzIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadQingbzAsync(Action.Desktop, pushNow);
            } else if (SimpleIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadSimpleAsync(Action.Desktop, pushNow);
            } else if (SkitterIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadSkitterAsync(Action.Desktop, pushNow);
            } else if (SnakeIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadSnakeAsync(Action.Desktop, pushNow);
            } else if (TimelineIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadTimelineAsync(Action.Desktop, pushNow);
            } else if (ToopicIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadToopicAsync(Action.Desktop, pushNow);
            } else if (VenusIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadVenusAsync(Action.Desktop, pushNow);
            } else if (WallhavenIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadWallhavenAsync(Action.Desktop, pushNow);
            } else if (WallhereIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadWallhereAsync(Action.Desktop, pushNow);
            } else if (WallpaperupIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadWallpaperupAsync(Action.Desktop, pushNow);
            } else if (YmyouliIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadYmyouliAsync(Action.Desktop, pushNow);
            } else if (ZzzmhIni.GetId().Equals(ini.DesktopProvider)) {
                res = await LoadZzzmhAsync(Action.Desktop, pushNow);
            }
            if (res) {
                localSettings.Values[tagDesktop] = (int)(localSettings.Values[tagDesktop] ?? 0) + 1;
            }
            LogUtil.I("PushDesktopAsync() " + res);
            return res;
        }

        private async Task<bool> PushLockAsync() {
            await FileUtil.WriteDosage(ini.LockProvider);
            bool res = false;
            if (AbyssIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadAbyssAsync(Action.Lock, pushNow);
            } else if (A3gIni.GetId().Equals(ini.LockProvider)) {
                res = await Load3gAsync(Action.Lock, pushNow);
            } else if (AdwestIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadAdwestAsync(Action.Lock, pushNow);
            } else if (BackieeIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadBackieeAsync(Action.Lock, pushNow);
            } else if (BingIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadBingAsync(Action.Lock, pushNow);
            } else if (ColorhubIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadColorhubAsync(Action.Lock, pushNow);
            } else if (EsoIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadEsoAsync(Action.Lock, pushNow);
            } else if (FavoriteIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadFavoriteAsync(Action.Lock, pushNow);
            } else if (GluttonIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadGluttonAsync(Action.Lock, pushNow);
            } else if (Himawari8Ini.GetId().Equals(ini.LockProvider)) {
                res = await LoadHimawari8Async(Action.Lock);
            } else if (HuamaoIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadHuamaoAsync(Action.Lock, pushNow);
            } else if (IuiIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadIuiAsync(Action.Lock, pushNow);
            } else if (LocalIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadLocalAsync(Action.Lock);
            } else if (LspIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadLspAsync(Action.Lock, pushNow);
            } else if (NasaIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadNasaAsync(Action.Lock, pushNow);
            } else if (NetbianIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadNetbianAsync(Action.Lock, pushNow);
            } else if (ObzhiIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadObzhiAsync(Action.Lock, pushNow);
            } else if (OneIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadOneAsync(Action.Lock, pushNow);
            } else if (PexelsIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadPexelsAsync(Action.Lock, pushNow);
            } else if (QingbzIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadQingbzAsync(Action.Lock, pushNow);
            } else if (SimpleIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadSimpleAsync(Action.Lock, pushNow);
            } else if (SkitterIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadSkitterAsync(Action.Lock, pushNow);
            } else if (SnakeIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadSnakeAsync(Action.Lock, pushNow);
            } else if (TimelineIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadTimelineAsync(Action.Lock, pushNow);
            } else if (ToopicIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadToopicAsync(Action.Lock, pushNow);
            } else if (VenusIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadVenusAsync(Action.Lock, pushNow);
            } else if (WallhavenIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadWallhavenAsync(Action.Lock, pushNow);
            } else if (WallhereIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadWallhereAsync(Action.Lock, pushNow);
            } else if (WallpaperupIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadWallpaperupAsync(Action.Lock, pushNow);
            } else if (YmyouliIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadYmyouliAsync(Action.Lock, pushNow);
            } else if (ZzzmhIni.GetId().Equals(ini.LockProvider)) {
                res = await LoadZzzmhAsync(Action.Lock, pushNow);
            }
            if (res) {
                localSettings.Values[tagLock] = (int)(localSettings.Values[tagLock] ?? 0) + 1;
            }
            LogUtil.I("PushLockAsync() " + res);
            return res;
        }

        private async Task<bool> PushTileAsync() {
            await FileUtil.WriteDosage(ini.Provider);
            bool res;
            if (A3gIni.GetId().Equals(ini.Provider)) {
                res = await Load3gAsync(Action.Tile, pushNow);
            } else if (AbyssIni.GetId().Equals(ini.Provider)) {
                res = await LoadAbyssAsync(Action.Tile, pushNow);
            } else if (AdwestIni.GetId().Equals(ini.Provider)) {
                res = await LoadAdwestAsync(Action.Tile, pushNow);
            } else if (BackieeIni.GetId().Equals(ini.Provider)) {
                res = await LoadBackieeAsync(Action.Tile, pushNow);
            } else if (BingIni.GetId().Equals(ini.Provider)) {
                res = await LoadBingAsync(Action.Tile, pushNow);
            } else if (ColorhubIni.GetId().Equals(ini.Provider)) {
                res = await LoadColorhubAsync(Action.Tile, pushNow);
            } else if (EsoIni.GetId().Equals(ini.Provider)) {
                res = await LoadEsoAsync(Action.Tile, pushNow);
            } else if (FavoriteIni.GetId().Equals(ini.Provider)) {
                res = await LoadFavoriteAsync(Action.Tile, pushNow);
            } else if (GluttonIni.GetId().Equals(ini.Provider)) {
                res = await LoadGluttonAsync(Action.Tile, pushNow);
            } else if (Himawari8Ini.GetId().Equals(ini.Provider)) {
                res = await LoadHimawari8Async(Action.Tile);
            } else if (HuamaoIni.GetId().Equals(ini.Provider)) {
                res = await LoadHuamaoAsync(Action.Tile, pushNow);
            } else if (IuiIni.GetId().Equals(ini.Provider)) {
                res = await LoadIuiAsync(Action.Tile, pushNow);
            } else if (LocalIni.GetId().Equals(ini.Provider)) {
                res = await LoadLocalAsync(Action.Tile);
            } else if (LspIni.GetId().Equals(ini.Provider)) {
                res = await LoadLspAsync(Action.Tile, pushNow);
            } else if (NasaIni.GetId().Equals(ini.Provider)) {
                res = await LoadNasaAsync(Action.Tile, pushNow);
            } else if (NetbianIni.GetId().Equals(ini.Provider)) {
                res = await LoadNetbianAsync(Action.Tile, pushNow);
            } else if (ObzhiIni.GetId().Equals(ini.Provider)) {
                res = await LoadObzhiAsync(Action.Tile, pushNow);
            } else if (OneIni.GetId().Equals(ini.Provider)) {
                res = await LoadOneAsync(Action.Tile, pushNow);
            } else if (PexelsIni.GetId().Equals(ini.Provider)) {
                res = await LoadPexelsAsync(Action.Tile, pushNow);
            } else if (QingbzIni.GetId().Equals(ini.Provider)) {
                res = await LoadQingbzAsync(Action.Tile, pushNow);
            } else if (SimpleIni.GetId().Equals(ini.Provider)) {
                res = await LoadSimpleAsync(Action.Tile, pushNow);
            } else if (SkitterIni.GetId().Equals(ini.Provider)) {
                res = await LoadSkitterAsync(Action.Tile, pushNow);
            } else if (SnakeIni.GetId().Equals(ini.Provider)) {
                res = await LoadSnakeAsync(Action.Tile, pushNow);
            } else if (TimelineIni.GetId().Equals(ini.Provider)) {
                res = await LoadTimelineAsync(Action.Tile, pushNow);
            } else if (ToopicIni.GetId().Equals(ini.Provider)) {
                res = await LoadToopicAsync(Action.Tile, pushNow);
            } else if (VenusIni.GetId().Equals(ini.Provider)) {
                res = await LoadVenusAsync(Action.Tile, pushNow);
            } else if (WallhavenIni.GetId().Equals(ini.Provider)) {
                res = await LoadWallhavenAsync(Action.Tile, pushNow);
            } else if (WallhereIni.GetId().Equals(ini.Provider)) {
                res = await LoadWallhereAsync(Action.Tile, pushNow);
            } else if (WallpaperupIni.GetId().Equals(ini.Provider)) {
                res = await LoadWallpaperupAsync(Action.Tile, pushNow);
            } else if (YmyouliIni.GetId().Equals(ini.Provider)) {
                res = await LoadYmyouliAsync(Action.Tile, pushNow);
            } else if (ZzzmhIni.GetId().Equals(ini.Provider)) {
                res = await LoadZzzmhAsync(Action.Tile, pushNow);
            } else { // 设置默认值
                res = await LoadBingAsync(Action.Tile, pushNow);
            }
            if (res) {
                localSettings.Values[tagTile] = (int)(localSettings.Values[tagTile] ?? 0) + 1;
            }
            LogUtil.I("PushTileAsync() " + res);
            return res;
        }

        private async Task<bool> SetDesktopBgAsync(StorageFile fileImg) {
            BasicProperties properties = await fileImg.GetBasicPropertiesAsync();
            if (properties.Size == 0) {
                return false;
            }
            return await UserProfilePersonalizationSettings.Current.TrySetWallpaperImageAsync(fileImg);
        }

        private async Task<bool> SetLockBgAsync(StorageFile fileImg) {
            BasicProperties properties = await fileImg.GetBasicPropertiesAsync();
            if (properties.Size == 0) {
                return false;
            }
            return await UserProfilePersonalizationSettings.Current.TrySetLockScreenImageAsync(fileImg);
        }

        //private bool ShowToast(string urlThumb) {
        //    if (string.IsNullOrEmpty(urlThumb)) {
        //        return false;
        //    }
        //    // ResourceLoader.GetForCurrentView().GetString("ToastTitle")
        //    string content = string.Format("<toast><visual>" +
        //        "<binding template='ToastGeneric'>" +
        //        "<image src='{0}' placement='hero' />" +
        //        "<text hint-maxLines='1'>{1}</text>" +
        //        "</binding></visual>" +
        //        "<actions>" +
        //        "<action content='{2}' arguments='' activationType='background' />" +
        //        "<action content='{3}' arguments='' activationType='background' />" +
        //        "</actions></toast>", urlThumb, "今日一图", "设为桌面", "设为锁屏");
        //    XmlDocument doc = new XmlDocument();
        //    doc.LoadXml(content);
        //    ToastNotification toast = new ToastNotification(doc) {
        //        ExpirationTime = DateTime.Now.AddDays(1)
        //    };
        //    ToastNotificationManager.CreateToastNotifier().Show(toast);
        //    return true;
        //}

        private bool SetTileBg(string urlThumb) {
            if (string.IsNullOrEmpty(urlThumb)) {
                return false;
            }
            string content = string.Format("<tile><visual>" +
                "<binding template='TileWide'>" +
                "<image src='{0}' placement='background' />" +
                "</binding>" +
                "<binding template='TileLarge'>" +
                "<image src='{0}' placement='background' />" +
                "</binding>" +
                "</visual></tile>", urlThumb);
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(content);
            TileNotification notification = new TileNotification(doc);
            TileUpdateManager.CreateTileUpdaterForApplication().Update(notification);
            return true;
        }

        private async Task<bool> SetTileBgForHimawari8(StorageFile fileImg) {
            BasicProperties properties = await fileImg.GetBasicPropertiesAsync();
            if (properties.Size == 0) {
                return false;
            }
            string content = string.Format("<tile><visual>" +
                "<binding template='TileMedium'>" +
                "<image src='{0}' placement='background' />" +
                "</binding>" +
                "<binding template='TileWide'>" +
                "<image src='{0}' placement='background' />" +
                "</binding>" +
                "<binding template='TileLarge'>" +
                "<image src='{0}' placement='background' />" +
                "</binding>" +
                "</visual></tile>", fileImg.Path);
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(content);
            TileNotification notification = new TileNotification(doc);
            TileUpdateManager.CreateTileUpdaterForApplication().Update(notification);
            return true;
        }

        private async Task<StorageFile> DownloadImgAsync(string urlImg, Action action, float offset = -1f, float ratio = -1f) {
            string cacheName;
            switch (action) {
                case Action.Desktop:
                    cacheName = "desktop";
                    break;
                case Action.Lock:
                    cacheName = "lock";
                    break;
                case Action.Tile:
                default:
                    cacheName = "tile";
                    break;
            }
            StorageFolder folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("wallpaper",
                CreationCollisionOption.OpenIfExists);
            StorageFile file = await folder.CreateFileAsync(string.Format("{0}-{1}.jpg", cacheName, DateTime.Now.ToString("yyyyMMddHH00")),
                CreationCollisionOption.ReplaceExisting);
            if (string.IsNullOrEmpty(urlImg)) {
                LogUtil.E("DownloadImgAsync() invalid url");
                return file;
            }
            Uri uriImg = new Uri(urlImg);
            if (uriImg.IsFile) {
                StorageFile srcFile = await StorageFile.GetFileFromPathAsync(urlImg);
                await srcFile.CopyAndReplaceAsync(file);
            } else {
                BackgroundDownloader downloader = new BackgroundDownloader();
                DownloadOperation operation = downloader.CreateDownload(uriImg, file);
                DownloadOperation resOperation = await operation.StartAsync().AsTask();
                if (resOperation.Progress.Status != BackgroundTransferStatus.Completed) {
                    LogUtil.E("DownloadImgAsync() download error");
                    return file;
                }
            }
            
            if (offset >= 0 && ratio >= 0) {
                CanvasDevice device = CanvasDevice.GetSharedDevice();
                CanvasBitmap bitmap = null;
                using (var stream = await file.OpenReadAsync()) {
                    bitmap = await CanvasBitmap.LoadAsync(device, stream);
                }
                if (bitmap == null) {
                    return file;
                }
                //DisplayInformation info = DisplayInformation.GetForCurrentView();
                //Size monitorSize = new Size((int)info.ScreenWidthInRawPixels, (int)info.ScreenHeightInRawPixels);
                long screen = (long)(localSettings.Values["Resolution"] ?? 0);
                long screenW = (screen & 0xffff0000) >> 16;
                long screenH = screen & 0x0000ffff;
                if (screen == 0) {
                    screenW = 1920;
                    screenH = 1080;
                }
                float canvasW, canvasH;
                if (screenW > screenH) {
                    canvasH = bitmap.SizeInPixels.Height / ratio;
                    canvasW = canvasH / screenH * screenW;
                } else {
                    canvasW = bitmap.SizeInPixels.Width / ratio;
                    canvasH = canvasW / screenW * screenH;
                }
                CanvasRenderTarget target = new CanvasRenderTarget(device, canvasW, canvasH, 96);
                using (var session = target.CreateDrawingSession()) {
                    session.Clear(Colors.Black);
                    session.DrawImage(bitmap, (canvasW + bitmap.SizeInPixels.Width) * offset - bitmap.SizeInPixels.Width,
                        canvasH / 2 - bitmap.SizeInPixels.Height / 2);
                }
                await file.DeleteAsync(); // 删除原图
                file = await folder.CreateFileAsync(string.Format("{0}-reset-{1}.png", cacheName, DateTime.Now.ToString("yyyyMMddHH00")),
                    CreationCollisionOption.ReplaceExisting);
                await target.SaveAsync(file.Path, CanvasBitmapFileFormat.Png, 1.0f);
            }

            BasicProperties properties = await file.GetBasicPropertiesAsync();
            LogUtil.I("DownloadImgAsync() " + file.Name + " " + properties.Size);
            // 删除上次重图
            IReadOnlyList<StorageFile> oldCacheFiles = (await folder.GetFilesAsync())
                .Where(f => f.Name.StartsWith(cacheName) && !f.Name.Equals(file.Name))
                .OrderByDescending(f => f.Name).ToList();
            if (oldCacheFiles.Count > 0) {
                BasicProperties propertiesLast = await oldCacheFiles[0].GetBasicPropertiesAsync();
                BasicProperties propertiesThis = await file.GetBasicPropertiesAsync();
                if (propertiesLast.Size == propertiesThis.Size) {
                    LogUtil.I("DownloadImgAsync() delete duplicated: " + oldCacheFiles[0].Name + " (this: " + file.Name);
                    await oldCacheFiles[0].DeleteAsync();
                }
            }
            return file;
        }

        private async Task<bool> Load3gAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(A3gIni.GetId(), ini.A3g.Order, ini.A3g.CateHow, ini.A3g.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("Load3gAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("Load3gAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/3g/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.A3g.Order, ini.A3g.CateHow, ini.A3g.CateWhat);
                LogUtil.I("Load3gAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(A3gIni.GetId(), ini.A3g.Order, ini.A3g.CateHow, ini.A3g.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("Load3gAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("Load3gAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadAbyssAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(AbyssIni.GetId(), ini.Abyss.Order, ini.Abyss.CateHow, ini.Abyss.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadAbyssAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadAbyssAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/abyss/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Abyss.Order, ini.Abyss.CateHow, ini.Abyss.CateWhat);
                LogUtil.I("LoadAbyssAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(AbyssIni.GetId(), ini.Abyss.Order, ini.Abyss.CateHow, ini.Abyss.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadAbyssAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadAbyssAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadAdwestAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(AdwestIni.GetId(), ini.Adwest.Order, ini.Adwest.CateHow, ini.Adwest.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadAdwestAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadAdwestAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/adwest/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Adwest.Order, ini.Adwest.CateHow, ini.Adwest.CateWhat);
                LogUtil.I("LoadAdwestAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(AdwestIni.GetId(), ini.Adwest.Order, ini.Adwest.CateHow, ini.Adwest.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadAdwestAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadAdwestAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadBackieeAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(BackieeIni.GetId(), ini.Backiee.Order, ini.Backiee.CateHow, ini.Backiee.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadBackieeAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadBackieeAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/backiee/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Backiee.Order, ini.Backiee.CateHow, ini.Backiee.CateWhat);
                LogUtil.I("LoadBackieeAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(BackieeIni.GetId(), ini.Backiee.Order, ini.Backiee.CateHow, ini.Backiee.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadBackieeAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadBackieeAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadBingAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(BingIni.GetId(), ini.Bing.Order, ini.Bing.CateHow, ini.Bing.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        if ("date".Equals(ini.Bing.Order)) {
                            data = api.Data[0];
                        } else {
                            data = api.Data[new Random().Next(api.Data.Count)];
                        }
                        LogUtil.I("LoadBingAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadBingAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/bing/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Bing.Order, ini.Bing.CateHow, ini.Bing.CateWhat);
                LogUtil.I("LoadBingAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                if ("date".Equals(ini.Bing.Order)) {
                    data = api.Data[0];
                } else {
                    data = api.Data[new Random().Next(api.Data.Count)];
                }
                await FileUtil.WriteProviderCache(BingIni.GetId(), ini.Bing.Order, ini.Bing.CateHow, ini.Bing.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadBingAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadBingAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        //private async Task<bool> LoadBingAltAsync(Action action) {
        //    const string URL_API_HOST = "https://global.bing.com";
        //    const string URL_CND_HOST = "http://s.cn.bing.net";
        //    const string URL_API = URL_API_HOST + "/HPImageArchive.aspx?pid=hp&format=js&uhd=1&idx=0&n=1";
        //    LogUtil.I("LoadBingAltAsync() api url: " + URL_API);
        //    bool cn = "CN".Equals(GlobalizationPreferences.HomeGeographicRegion);
        //    HttpClient client = new HttpClient();
        //    string jsonData = await client.GetStringAsync(URL_API);
        //    BingApi api = JsonConvert.DeserializeObject<BingApi>(jsonData);
        //    if (action == Action.Tile) {
        //        string urlThumb = string.Format("{0}{1}_400x240.jpg", cn ? URL_CND_HOST : URL_API_HOST, api.Images[0].UrlBase);
        //        LogUtil.I("LoadBingAltAsync() thumb url: " + urlThumb);
        //        return SetTileBg(urlThumb);
        //    } else {
        //        string urlUhd = string.Format("{0}{1}_UHD.jpg", cn ? URL_CND_HOST : URL_API_HOST, api.Images[0].UrlBase);
        //        LogUtil.I("LoadBingAltAsync() img url: " + urlUhd);
        //        StorageFile fileImg = await DownloadImgAsync(urlUhd, action);
        //        if (action == Action.Lock) {
        //            return await SetLockBgAsync(fileImg);
        //        } else {
        //            return await SetDesktopBgAsync(fileImg);
        //        }
        //    }
        //}

        private async Task<bool> LoadColorhubAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(ColorhubIni.GetId(), ini.Colorhub.Order, ini.Colorhub.CateHow, ini.Colorhub.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadColorhubAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadColorhubAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/colorhub/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Colorhub.Order, ini.Colorhub.CateHow, ini.Colorhub.CateWhat);
                LogUtil.I("LoadColorhubAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(ColorhubIni.GetId(), ini.Colorhub.Order, ini.Colorhub.CateHow, ini.Colorhub.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadColorhubAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadColorhubAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadEsoAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(EsoIni.GetId(), ini.Eso.Order, ini.Eso.CateHow, ini.Eso.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadEsoAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadEsoAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/eso/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Eso.Order, ini.Eso.CateHow, ini.Eso.CateWhat);
                LogUtil.I("LoadEsoAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(EsoIni.GetId(), ini.Eso.Order, ini.Eso.CateHow, ini.Eso.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadEsoAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadEsoAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadFavoriteAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(FavoriteIni.GetId(), ini.Favorite.Order, "", "", ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadFavoriteAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadFavoriteAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/snake/favorite?order={0}";
                string urlApi = string.Format(URL_API, ini.Favorite.Order);
                LogUtil.I("LoadFavoriteAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(FavoriteIni.GetId(), ini.Favorite.Order, "", "", ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadFavoriteAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadFavoriteAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadGluttonAsync(Action action, bool forceReload = false) {
            GluttonApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(GluttonIni.GetId(), ini.Glutton.Order, ini.Glutton.CateHow, ini.Glutton.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GluttonApi api = JsonConvert.DeserializeObject<GluttonApi>(jsonData);
                        if ("date".Equals(ini.Glutton.Order) && string.IsNullOrEmpty(ini.Glutton.CateHow) && string.IsNullOrEmpty(ini.Glutton.CateWhat)) {
                            List<GluttonApiData> dataPhase = api.Data.Where(x => x.Phase == api.Data[0].Phase).ToList();
                            data = dataPhase[new Random().Next(dataPhase.Count)];
                        } else {
                            data = api.Data[new Random().Next(api.Data.Count)];
                        }
                        LogUtil.I("LoadGluttonAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadGluttonAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/glutton/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Glutton.Order, ini.Glutton.CateHow, ini.Glutton.CateWhat);
                LogUtil.I("LoadGluttonAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GluttonApi api = JsonConvert.DeserializeObject<GluttonApi>(jsonData);
                if ("date".Equals(ini.Glutton.Order) && string.IsNullOrEmpty(ini.Glutton.CateHow) && string.IsNullOrEmpty(ini.Glutton.CateWhat)) {
                    List<GluttonApiData> dataPhase = api.Data.Where(x => x.Phase == api.Data[0].Phase).ToList();
                    data = dataPhase[new Random().Next(dataPhase.Count)];
                } else {
                    data = api.Data[new Random().Next(api.Data.Count)];
                }
                await FileUtil.WriteProviderCache(GluttonIni.GetId(), ini.Glutton.Order, ini.Glutton.CateHow, ini.Glutton.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadGluttonAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadGluttonAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadHimawari8Async(Action action) {
            const string URL_API = "https://himawari8.nict.go.jp/img/D531106/latest.json?_=";
            const string URL_IMG = "https://himawari8.nict.go.jp/img/D531106/1d/550/{0}_0_0.png";
            string urlApi = URL_API + DateUtil.CurrentTimeMillis();
            LogUtil.I("LoadHimawari8Async() api url: " + urlApi);
            HttpClient client = new HttpClient();
            string jsonData = await client.GetStringAsync(urlApi);
            //Match match = Regex.Match(jsonData, @"""date"": ?""(.+?)""");
            //DateTime time = DateTime.ParseExact(match.Groups[1].Value, "yyyy-MM-dd HH:mm:ss",
            //    new System.Globalization.CultureInfo("en-US"));
            Himawari8Api api = JsonConvert.DeserializeObject<Himawari8Api>(jsonData);
            if (!DateTime.TryParse(api.Date, out DateTime time)) { // UTC时间
                time = DateTime.UtcNow.AddMinutes(-25);
            }
            string urlUhd = string.Format(URL_IMG, time.ToString(@"yyyy\/MM\/dd\/HHmmss"));
            LogUtil.I("LoadHimawari8Async() img url: " + urlUhd);
            if (action == Action.Tile) {
                StorageFile fileImg = await DownloadImgAsync(urlUhd, action);
                return await SetTileBgForHimawari8(fileImg);
            } else {
                StorageFile fileImg = await DownloadImgAsync(urlUhd, action, ini.Himawari8.Offset, ini.Himawari8.Ratio);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadHuamaoAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(HuamaoIni.GetId(), ini.Huamao.Order, ini.Huamao.CateHow, ini.Huamao.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadHuamaoAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadHuamaoAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/huamao/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Huamao.Order, ini.Huamao.CateHow, ini.Huamao.CateWhat);
                LogUtil.I("LoadHuamaoAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(HuamaoIni.GetId(), ini.Huamao.Order, ini.Huamao.CateHow, ini.Huamao.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadHuamaoAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadHuamaoAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadIuiAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(IuiIni.GetId(), ini.Iui.Order, ini.Iui.CateHow, ini.Iui.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadIuiAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadIuiAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/iui/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Iui.Order, ini.Iui.CateHow, ini.Iui.CateWhat);
                LogUtil.I("LoadIuiAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(IuiIni.GetId(), ini.Iui.Order, ini.Iui.CateHow, ini.Iui.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadIuiAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadIuiAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadLocalAsync(Action action) {
            StorageFolder folder = null;
            if (!string.IsNullOrEmpty(ini.Folder)) {
                try {
                    folder = await StorageFolder.GetFolderFromPathAsync(ini.Folder.Replace("/", "\\"));
                } catch (FileNotFoundException ex) { // 指定的文件夹不存在
                    LogUtil.E("LoadLocalAsync() " + ex.Message);
                } catch (UnauthorizedAccessException ex) { // 您无权访问指定文件夹
                    LogUtil.E("LoadLocalAsync() " + ex.Message);
                } catch (ArgumentException ex) { // 路径不能是相对路径或 URI
                    LogUtil.E("LoadLocalAsync() " + ex.Message);
                } catch (Exception ex) {
                    LogUtil.E("LoadLocalAsync() " + ex.Message);
                }
            }
            if (folder == null) {
                folder = await KnownFolders.PicturesLibrary.CreateFolderAsync(AppInfo.Current.DisplayInfo.DisplayName,
                    CreationCollisionOption.OpenIfExists);
            }
            // CommonFileQuery.OrderByDate 只能对库中的文件夹或家庭组文件夹中使用此选项（库外文件夹将导致异常）；深层简单列表
            // CommonFileQuery.DefaultQuery 此选项用于任何存储位置；浅表列表
            IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
            List<StorageFile> srcFiles = files.Where(x => x.ContentType.StartsWith("image")).ToList();
            StorageFile fileSrc;
            if ("date".Equals(ini.Local.Order)) {
                srcFiles = srcFiles.OrderByDescending(f => f.DateCreated.DateTime).ToList();
                fileSrc = srcFiles[new Random().Next(Math.Min(srcFiles.Count, 99))];
            } else { // random
                srcFiles = srcFiles.OrderBy(f => Guid.NewGuid()).ToList();
                fileSrc = srcFiles[new Random().Next(srcFiles.Count)];
            }
            LogUtil.I("LoadLocalAsync() img file: " + fileSrc.Path);
            if (action == Action.Tile) {
                // 生成缩略图
                // TODO：无法保持原图比例
                StorageFolder folderWp = await ApplicationData.Current.LocalFolder.CreateFolderAsync("wallpaper",
                    CreationCollisionOption.OpenIfExists);
                StorageFile fileThumb = await folderWp.CreateFileAsync(string.Format("tile-{0}.jpg", DateTime.Now.ToString("yyyyMMddHH00")),
                    CreationCollisionOption.ReplaceExisting);
                StorageItemThumbnail thumb = await fileSrc.GetThumbnailAsync(ThumbnailMode.PicturesView);
                Windows.Storage.Streams.Buffer buffer = new Windows.Storage.Streams.Buffer(Convert.ToUInt32(thumb.Size));
                using (var stream = await fileThumb.OpenAsync(FileAccessMode.ReadWrite)) {
                    await stream.WriteAsync(await thumb.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None));
                }
                LogUtil.I("LoadLocalAsync() thumb file: " + fileThumb.Path);
                return SetTileBg(fileThumb.Path);
            } else {
                StorageFile fileImg = await DownloadImgAsync(fileSrc.Path, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadLspAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(LspIni.GetId(), ini.Lsp.Order, ini.Lsp.CateHow, ini.Lsp.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadLspAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadLspAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/lsp/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Lsp.Order, ini.Lsp.CateHow, ini.Lsp.CateWhat);
                LogUtil.I("LoadLspAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(LspIni.GetId(), ini.Lsp.Order, ini.Lsp.CateHow, ini.Lsp.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadLspAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadLspAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadNasaAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(NasaIni.GetId(), ini.Nasa.Order, ini.Nasa.CateHow, ini.Nasa.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        if ("date".Equals(ini.Bing.Order)) {
                            data = api.Data[0];
                        } else {
                            data = api.Data[new Random().Next(api.Data.Count)];
                        }
                        LogUtil.I("LoadNasaAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadNasaAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/nasa/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Nasa.Order, ini.Nasa.CateHow, ini.Nasa.CateWhat);
                LogUtil.I("LoadNasaAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                if ("date".Equals(ini.Bing.Order)) {
                    data = api.Data[0];
                } else {
                    data = api.Data[new Random().Next(api.Data.Count)];
                }
                await FileUtil.WriteProviderCache(NasaIni.GetId(), ini.Nasa.Order, ini.Nasa.CateHow, ini.Nasa.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadNasaAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadNasaAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadNetbianAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(NetbianIni.GetId(), ini.Netbian.Order, ini.Netbian.CateHow, ini.Netbian.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadNetbianAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadNetbianAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/netbian/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Netbian.Order, ini.Netbian.CateHow, ini.Netbian.CateWhat);
                LogUtil.I("LoadNetbianAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(NetbianIni.GetId(), ini.Netbian.Order, ini.Netbian.CateHow, ini.Netbian.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadNetbianAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadNetbianAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadObzhiAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(ObzhiIni.GetId(), ini.Obzhi.Order, ini.Obzhi.CateHow, ini.Obzhi.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadObzhiAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadObzhiAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/obzhi/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Obzhi.Order, ini.Obzhi.CateHow, ini.Obzhi.CateWhat);
                LogUtil.I("LoadObzhiAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(ObzhiIni.GetId(), ini.Obzhi.Order, ini.Obzhi.CateHow, ini.Obzhi.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadObzhiAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadObzhiAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadOneAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(OneIni.GetId(), ini.One.Order, ini.One.CateHow, ini.One.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        if ("date".Equals(ini.Bing.Order)) {
                            data = api.Data[0];
                        } else {
                            data = api.Data[new Random().Next(api.Data.Count)];
                        }
                        LogUtil.I("LoadOneAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadOneAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/one/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.One.Order, ini.One.CateHow, ini.One.CateWhat);
                LogUtil.I("LoadOneAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                if ("date".Equals(ini.Bing.Order)) {
                    data = api.Data[0];
                } else {
                    data = api.Data[new Random().Next(api.Data.Count)];
                }
                await FileUtil.WriteProviderCache(OneIni.GetId(), ini.One.Order, ini.One.CateHow, ini.One.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadOneAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadOneAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        //private async Task<bool> LoadOneAltAsync(Action action) {
        //    const string URL_TOKEN = "http://m.wufazhuce.com/one";
        //    const string URL_API = "http://m.wufazhuce.com/one/ajaxlist/0?_token={0}";
        //    HttpClient client = new HttpClient();
        //    HttpResponseMessage msg = await client.GetAsync(URL_TOKEN); // cookie 无需手动取，自动包含
        //    string htmlData = await msg.Content.ReadAsStringAsync();
        //    Match match = Regex.Match(htmlData, @"One.token ?= ?[""'](.+?)[""']");
        //    string token = match.Groups[1].Value;
        //    string urlApi = string.Format(URL_API, token);
        //    LogUtil.I("LoadOneAsync() api url: " + urlApi);
        //    string jsonData = await client.GetStringAsync(urlApi);
        //    match = Regex.Match(jsonData, @"""img_url"": ?""(.+?)""");
        //    string urlUhd = Regex.Unescape(match.Groups[1].Value); // 反转义
        //    LogUtil.I("LoadOneAsync() img url: " + urlUhd);
        //    if (action == Action.Tile) {
        //        return SetTileBg(urlUhd);
        //    } else {
        //        StorageFile fileImg = await DownloadImgAsync(urlUhd, action);
        //        if (action == Action.Lock) {
        //            return await SetLockBgAsync(fileImg);
        //        } else {
        //            return await SetDesktopBgAsync(fileImg);
        //        }
        //    }
        //}

        private async Task<bool> LoadPexelsAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(PexelsIni.GetId(), ini.Pexels.Order, ini.Pexels.CateHow, ini.Pexels.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadPexelsAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadPexelsAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/pexels/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Pexels.Order, ini.Pexels.CateHow, ini.Pexels.CateWhat);
                LogUtil.I("LoadPexelsAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(PexelsIni.GetId(), ini.Pexels.Order, ini.Pexels.CateHow, ini.Pexels.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadPexelsAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadPexelsAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadQingbzAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(QingbzIni.GetId(), ini.Qingbz.Order, ini.Qingbz.CateHow, ini.Qingbz.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadQingbzAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadQingbzAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/qingbz/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Qingbz.Order, ini.Qingbz.CateHow, ini.Qingbz.CateWhat);
                LogUtil.I("LoadQingbzAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(QingbzIni.GetId(), ini.Qingbz.Order, ini.Qingbz.CateHow, ini.Qingbz.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadQingbzAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadQingbzAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadSimpleAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(SimpleIni.GetId(), ini.Simple.Order, ini.Simple.CateHow, ini.Simple.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadSimpleAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadSimpleAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/simple/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Simple.Order, ini.Simple.CateHow, ini.Simple.CateWhat);
                LogUtil.I("LoadSimpleAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(SimpleIni.GetId(), ini.Simple.Order, ini.Simple.CateHow, ini.Simple.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadSimpleAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadSimpleAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadSkitterAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(SkitterIni.GetId(), ini.Skitter.Order, ini.Skitter.CateHow, ini.Skitter.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadSkitterAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadSkitterAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/skitter/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Skitter.Order, ini.Skitter.CateHow, ini.Skitter.CateWhat);
                LogUtil.I("LoadSkitterAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(SkitterIni.GetId(), ini.Skitter.Order, ini.Skitter.CateHow, ini.Skitter.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadSkitterAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadSkitterAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadSnakeAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(SnakeIni.GetId(), ini.Snake.Order, ini.Snake.CateHow, ini.Snake.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadSnakeAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadSnakeAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/snake/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Snake.Order, ini.Snake.CateHow, ini.Snake.CateWhat);
                LogUtil.I("LoadSnakeAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(SnakeIni.GetId(), ini.Snake.Order, ini.Snake.CateHow, ini.Snake.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadSnakeAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadSnakeAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadTimelineAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(TimelineIni.GetId(), ini.Timeline.Order, ini.Timeline.CateHow, ini.Timeline.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        if ("date".Equals(ini.Bing.Order)) {
                            data = api.Data[0];
                        } else {
                            data = api.Data[new Random().Next(api.Data.Count)];
                        }
                        LogUtil.I("LoadTimelineAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadTimelineAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/timeline/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Timeline.Order, ini.Timeline.CateHow, ini.Timeline.CateWhat);
                LogUtil.I("LoadTimelineAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                if ("date".Equals(ini.Bing.Order)) {
                    data = api.Data[0];
                } else {
                    data = api.Data[new Random().Next(api.Data.Count)];
                }
                await FileUtil.WriteProviderCache(TimelineIni.GetId(), ini.Timeline.Order, ini.Timeline.CateHow, ini.Timeline.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadTimelineAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadTimelineAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadToopicAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(ToopicIni.GetId(), ini.Toopic.Order, ini.Toopic.CateHow, ini.Toopic.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadToopicAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadToopicAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/toopic/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Toopic.Order, ini.Toopic.CateHow, ini.Toopic.CateWhat);
                LogUtil.I("LoadToopicAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(ToopicIni.GetId(), ini.Toopic.Order, ini.Toopic.CateHow, ini.Toopic.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadToopicAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadToopicAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadVenusAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(VenusIni.GetId(), ini.Venus.Order, ini.Venus.CateHow, ini.Venus.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadVenusAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadVenusAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/venus/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Venus.Order, ini.Venus.CateHow, ini.Venus.CateWhat);
                LogUtil.I("LoadVenusAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(VenusIni.GetId(), ini.Venus.Order, ini.Venus.CateHow, ini.Venus.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadVenusAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadVenusAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadWallhavenAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(WallhavenIni.GetId(), ini.Wallhaven.Order, ini.Wallhaven.CateHow, ini.Wallhaven.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadWallhavenAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadWallhavenAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/wallhaven/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Wallhaven.Order, ini.Wallhaven.CateHow, ini.Wallhaven.CateWhat);
                LogUtil.I("LoadWallhavenAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(WallhavenIni.GetId(), ini.Wallhaven.Order, ini.Wallhaven.CateHow, ini.Wallhaven.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadWallhavenAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadWallhavenAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadWallhereAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(WallhereIni.GetId(), ini.Wallhere.Order, ini.Wallhere.CateHow, ini.Wallhere.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadWallhereAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadWallhereAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/wallhere/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Wallhere.Order, ini.Wallhere.CateHow, ini.Wallhere.CateWhat);
                LogUtil.I("LoadWallhereAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(WallhereIni.GetId(), ini.Wallhere.Order, ini.Wallhere.CateHow, ini.Wallhere.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadWallhereAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadWallhereAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadWallpaperupAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(WallpaperupIni.GetId(), ini.Wallpaperup.Order, ini.Wallpaperup.CateHow, ini.Wallpaperup.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadWallpaperupAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadWallpaperupAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/wallpaperup/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Wallpaperup.Order, ini.Wallpaperup.CateHow, ini.Wallpaperup.CateWhat);
                LogUtil.I("LoadWallpaperupAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(WallpaperupIni.GetId(), ini.Wallpaperup.Order, ini.Wallpaperup.CateHow, ini.Wallpaperup.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadWallpaperupAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadWallpaperupAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadYmyouliAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(YmyouliIni.GetId(), ini.Ymyouli.Order, ini.Ymyouli.CateHow, ini.Ymyouli.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadYmyouliAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadYmyouliAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/ymyouli/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Ymyouli.Order, ini.Ymyouli.CateHow, ini.Ymyouli.CateWhat);
                LogUtil.I("LoadYmyouliAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(YmyouliIni.GetId(), ini.Ymyouli.Order, ini.Ymyouli.CateHow, ini.Ymyouli.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadYmyouliAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadYmyouliAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }

        private async Task<bool> LoadZzzmhAsync(Action action, bool forceReload = false) {
            GeneralApiData data = null;
            if (!forceReload) {
                string jsonData = await FileUtil.ReadProviderCache(ZzzmhIni.GetId(), ini.Zzzmh.Order, ini.Zzzmh.CateHow, ini.Zzzmh.CateWhat, ini.User);
                if (!string.IsNullOrEmpty(jsonData)) {
                    try {
                        GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                        data = api.Data[new Random().Next(api.Data.Count)];
                        LogUtil.I("LoadZzzmhAsync() cache from disk");
                    } catch (Exception e) {
                        LogUtil.E("LoadZzzmhAsync() " + e.Message);
                    }
                }
            }
            if (data == null) {
                const string URL_API = "https://api.nguaduot.cn/zzzmh/v3?order={0}&catehow={1}&catewhat={2}";
                string urlApi = string.Format(URL_API, ini.Zzzmh.Order, ini.Zzzmh.CateHow, ini.Zzzmh.CateWhat);
                LogUtil.I("LoadZzzmhAsync() api url: " + urlApi);
                HttpClient client = new HttpClient();
                HttpRequestMessage msgReq = new HttpRequestMessage(HttpMethod.Get, urlApi);
                msgReq.Headers.Add("Timeline-User", ini.UserEncoded());
                msgReq.Headers.Add("Timeline-Pwd", ini.PwdEncrypted());
                msgReq.Headers.Add("Timeline-Device", SysUtil.GetDeviceId());
                msgReq.Headers.Add("Timeline-Client", ini.Client ?? "");
                HttpResponseMessage res = await client.SendAsync(msgReq);
                string jsonData = await res.Content.ReadAsStringAsync();
                GeneralApi api = JsonConvert.DeserializeObject<GeneralApi>(jsonData);
                data = api.Data[new Random().Next(api.Data.Count)];
                await FileUtil.WriteProviderCache(ZzzmhIni.GetId(), ini.Zzzmh.Order, ini.Zzzmh.CateHow, ini.Zzzmh.CateWhat, ini.User, jsonData);
            }
            if (action == Action.Tile) {
                LogUtil.I("LoadZzzmhAsync() thumb url: " + data.ThumbUrl);
                return SetTileBg(data.ThumbUrl);
            } else {
                LogUtil.I("LoadZzzmhAsync() img url: " + data.ImgUrl);
                StorageFile fileImg = await DownloadImgAsync(data.ImgUrl, action);
                if (action == Action.Lock) {
                    return await SetLockBgAsync(fileImg);
                } else {
                    return await SetDesktopBgAsync(fileImg);
                }
            }
        }
    }
}
